package cqrtplm.aop;

import cn.hutool.core.collection.CollUtil;
import com.hustcad.plm.pdm.iba.model.dto.SaveObjIBADTO;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeValueService;
import com.hustcad.plm.pdm.middle.partbom.service.TyplmPdmPartService;
import com.hustcad.plm.pdm.partbom.dto.ModifyPartDTO;
import com.hustcad.plm.pdm.partbom.dto.PartBomTree;
import com.hustcad.plm.pdm.partbom.query.PartUsageCountQuery;
import com.hustcad.plm.pdm.partbom.service.TyplmPartService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartUsageService;
import com.hustcad.plm.pdm.partbom.vo.PartBomTreeByFilterVO;
import com.hustcad.plm.pdm.partbom.vo.usagecount.PartUsageCountVO;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.dto.constraint.IbaDTO;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.part.PartDO;
import com.ty.basic.vo.AttributeVO;
import cqrtplm.common.CommonService;
import cqrtplm.constant.RTPlmConstant;
import cqrtplm.mapper.DspfMbomBomMapper;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.hustcad.plm.pdm.series.service.impl.TyplmMulticharacterSeriesHelper.getNextVersion;

/**
 * 成品BOM搭建中获取限制派工的属性
 * 当零部件的待验证属性变为"Verified"时，检查使用该零部件的成品码下所有物料是否都已验证
 * 如果全部验证，则将成品码的限制派工属性改为"Normal"
 */
@Aspect
@Component
@Slf4j
public class RestrictedDispatchAOP {

    /**
     * 状态信息对象类型配置
     */
    @Value("${STATUS_INFO_OBJECTTYPE}")
    private String STATUSINFOOBJECTTYPE;

    /**
     * 状态信息产品代码配置
     */
    @Value("${STATUS_INFO_PRODUCTCODE}")
    private String STATUS_INFO_PRODUCTCODE;

    @Resource
    private TyplmPdmPartService typlmPdmPartService;
    @Resource
    private TyplmAttributeValueService typlmAttributeValueService;
    @Resource
    private DspfMbomBomMapper dspfMbomBomMapper;
    @Resource
    TyplmPartUsageService typlmPartUsageService;
    @Resource
    private CommonService commonService;
    @Resource
    private TyplmPartService typlmPartService;

    /**
     * 待验证属性名称常量
     */
    private static final String PENDINGVERIFICATION = "PendingVerification";

    /**
     * 已验证状态值常量
     */
    private static final String VERIFIED = "Verified";

    /**
     * 限制派工 ：正常
     */
    private static final String NORMAL = "Normal";
    /**
     * 限制派工 ：异常
     */
    private static final String LIMIT = "Limit";

    /**
     * 定义切入点，匹配TyplmPartController的updatePart方法
     */
    @Pointcut("execution(* com.hustcad.plm.pdm.partbom.controller.TyplmPartController.updatePart(..))")
    public void updatePartPointcut() {}

    /**
     * 在方法执行前拦截并获取参数
     *
     * @param joinPoint 连接点
     */
    @Before("updatePartPointcut()")
    public void beforeUpdatePart(JoinPoint joinPoint) {
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            // 只处理ModifyPartDTO类型的参数
            if (!(arg instanceof ModifyPartDTO)) {
                continue;
            }

            ModifyPartDTO modifyPartDTO = (ModifyPartDTO) arg;


            // 参数校验
            String partNumber = modifyPartDTO.getPartNumber();
            if (partNumber == null || partNumber.isEmpty()) {
                return;
            }

            // 通过传入的参数获取零部件编码
            PartDO partDO = typlmPdmPartService.queryLastPartDoByPartNumber(partNumber);
            if (partDO == null) {
                return;
            }

            // 获取分类名称是否为 物料码
            String typeName = dspfMbomBomMapper.selectTypeNameByTypeId(partDO.getTypeoid());
            if (typeName == null || !STATUSINFOOBJECTTYPE.equals(typeName)) {
                return;
            }

            // 构建零部件使用关系查询条件
            PartUsageCountQuery query = buildPartUsageQuery(partDO.getOid());

            // 查询该零部件的待验证属性
            Map<String, List<AttributeVO>> attrValueByOidAndKeys =
                    typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                            Collections.singletonList(partDO.getOid()),
                            TableTypeConstrant.TY_PART_OTYPE,
                            Collections.singletonList(PENDINGVERIFICATION));

            // 获取待验证属性值列表
            List<AttributeVO> verificationAttrs = Optional.ofNullable(attrValueByOidAndKeys)
                    .map(m -> m.get(String.valueOf(partDO.getOid())))
                    .orElse(Collections.emptyList());

            // 判断是否已验证，如果已验证则继续后续逻辑，如果为空或者未验证则结束切面
            if (verificationAttrs.isEmpty() ||
                    !VERIFIED.equals(verificationAttrs.get(0).getAttributeValue())) {
                return;
            }

            // 调用零部件的使用详情，通过这个可以查询到使用该物料的成品码
            Map<BigInteger, List<PartUsageCountVO>> usageMap = typlmPartUsageService.queryPartUsageParent(query);
            List<PartUsageCountVO> usages = usageMap.get(BigInteger.ZERO);

            if (usages == null || usages.isEmpty()) {
                return;
            }

            // 筛选出类型为成品码的使用记录
            List<PartUsageCountVO> productCodeUsages = filterProductCodeUsages(usages);

            if (productCodeUsages.isEmpty()) {
                return;
            }

            // 处理所有成品码记录
            processProductCodes(productCodeUsages);
        }
    }

    /**
     * 构建零部件使用关系查询条件
     *
     * @param partOid 零部件OID
     * @return 查询条件对象
     */
    private PartUsageCountQuery buildPartUsageQuery(BigInteger partOid) {
        PartUsageCountQuery query = new PartUsageCountQuery();
        query.setPartIdList(Collections.singletonList(partOid));
        query.setQueryScope("latest");
        query.setQueryLogic("direct");
        query.setLevel("0");
        return query;
    }

    /**
     * 筛选出类型为成品码的使用记录
     *
     * @param usages 所有使用记录
     * @return 成品码使用记录列表
     */
    private List<PartUsageCountVO> filterProductCodeUsages(List<PartUsageCountVO> usages) {
        return usages.stream()
                .filter(usage -> {
                    String typeName = dspfMbomBomMapper.selectTypeNameByTypeId(usage.getTypeoid());
                    return typeName != null && typeName.equalsIgnoreCase(STATUS_INFO_PRODUCTCODE);
                })
                .collect(Collectors.toList());
    }

    /**
     * 处理所有成品码记录
     *
     * @param productCodeUsages 成品码使用记录列表
     */
    private void processProductCodes(List<PartUsageCountVO> productCodeUsages) {
        for (PartUsageCountVO usage : productCodeUsages) {
            if (usage == null || usage.getOid() == null) {
                continue;
            }

            // 获取父级物料信息
            PartDO fatherPartDO = typlmPdmPartService.queryLastPartDoByPartNumber(usage.getPartnumber());
            if (fatherPartDO == null) {
                continue;
            }

            // 获取BOM结构树
            PartBomTreeByFilterVO bomTreeVO = commonService.queryChildParts(
                    fatherPartDO.getPartnumber(),
                    fatherPartDO.getOid().toString(),
                    "Design",
                    Boolean.FALSE,
                    null,
                    "N",
                    Boolean.TRUE
            );

            // 获取BOM树节点列表
            List<PartBomTree> treeNodes = bomTreeVO != null ? bomTreeVO.getPartBomTreeList() : null;
            if (treeNodes == null || treeNodes.isEmpty()) {
                continue;
            }

            // 处理BOM树节点属性
            handleTreeNodeAttributes(treeNodes, fatherPartDO);
        }
    }

    /**
     * 处理BOM树节点属性
     *
     * @param treeNodes BOM树节点列表
     */
    private void handleTreeNodeAttributes(List<PartBomTree> treeNodes, PartDO fatherPartDO) {
        // 收集所有子物料的OID
        List<BigInteger> oidList = treeNodes.stream()
                .filter(node -> node != null && node.getPartoid() != null)
                .map(node -> new BigInteger(node.getPartoid()))
                .distinct()
                .collect(Collectors.toList());

        if (oidList.isEmpty()) {
            return;
        }

        // 获取所有物料的待验证属性
        Map<String, List<AttributeVO>> attributeMap = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                oidList,
                TableTypeConstrant.TY_PART_OTYPE,
                Collections.singletonList(PENDINGVERIFICATION)
        );

        // 判断所有物料的待验证属性是否都为已验证
        boolean allVerified = false;
        if (attributeMap != null) {
            allVerified = attributeMap.values().stream()
                    .filter(Objects::nonNull)
                    .flatMap(List::stream)
                    .allMatch(attr -> attr != null && VERIFIED.equals(attr.getAttributeValue()));
        }

        // 如果全部已验证，则更新限制派工状态
        if (allVerified) {
            updateRestrictedDispatchStatus(fatherPartDO);
        }
    }

    /**
     * 更新限制派工状态
     *
     * @param
     */
    private void updateRestrictedDispatchStatus(PartDO fatherPartDO) {
        List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();


        // 创建IBA DTO对象
        IbaDTO ibaDTO = new IbaDTO();
        ibaDTO.setKey("RESTRICTEDDISPATCH");
        ibaDTO.setValue(NORMAL);

        // 创建保存对象IBA DTO
        SaveObjIBADTO dto = new SaveObjIBADTO();
        dto.setObjIbaList(Collections.singletonList(ibaDTO));
        dto.setCTyEntityBaseDO(new CTyEntityBaseDO(fatherPartDO.getOid(), TableTypeConstrant.TY_PART_OTYPE));
        objWithIbaList.add(dto);

        // 批量保存IBA属性
        if (!objWithIbaList.isEmpty()) {
            typlmAttributeValueService.batchSaveIBAByObjList(objWithIbaList, false);
        }
    }


    /**
     * 检查父级零部件下所有子零部件的验证状态，并更新父级的限制派工状态
     *
     * @param parentPart 父级零部件对象
     */
    public String checkChildrenAndSetParentStatus(PartDO parentPart) {
        // 获取BOM结构树
        PartBomTreeByFilterVO bomTreeVO = commonService.queryChildParts(
                parentPart.getPartnumber(),
                parentPart.getOid().toString(),
                "Design",
                Boolean.FALSE,
                null,
                "N",
                Boolean.TRUE
        );

        // 获取BOM树节点列表
        List<PartBomTree> treeNodes = bomTreeVO != null ? bomTreeVO.getPartBomTreeList() : null;
        if (treeNodes == null || treeNodes.isEmpty()) {
            // 如果没有子节点，默认设置为异常状态
            return LIMIT;
        }

        // 收集所有子物料的OID
        List<BigInteger> oidList = treeNodes.stream()
                .filter(node -> node != null && node.getPartoid() != null)
                .map(node -> new BigInteger(node.getPartoid()))
                .distinct()
                .collect(Collectors.toList());

        if (oidList.isEmpty()) {
            // 如果没有有效的子节点OID，默认设置为异常状态

            return LIMIT;
        }

        // 获取所有物料的指定属性
        Map<String, List<AttributeVO>> attributeMap = typlmAttributeValueService.getIbaAttrValueByOidAndKeys(
                oidList,
                TableTypeConstrant.TY_PART_OTYPE,
                Collections.singletonList(PENDINGVERIFICATION)
        );

        // 判断所有物料的指定属性是否都为已验证状态
        boolean allVerified = false;
        if (attributeMap != null) {
            allVerified = attributeMap.values().stream()
                    .filter(Objects::nonNull)
                    .flatMap(List::stream)
                    .allMatch(attr -> attr != null && VERIFIED.equals(attr.getAttributeValue()));
        }

        // 根据验证结果更新父级状态
        if (allVerified) {
            return NORMAL;
        } else {
            return LIMIT;
        }
    }


}
